package gitobject;



import repository.Repository;
import sha1.SHA1;

import zlib.ZLibUtils;
import fileoperation.FileReader;

import java.io.*;
import java.lang.reflect.Array;
import java.security.MessageDigest;
import java.util.*;


public class Tree extends GitObject{
    protected ArrayList<GitObject> treeList;	//GitObjects in tree

    public ArrayList<GitObject> getTreeList(){
        return treeList;
    }

    public Tree(){}

    /**
     * Constructor
     * @param file
     * @throws Exception
     */
    public Tree(File file) throws Exception {
        this.treeList = new ArrayList<>();
        this.fmt = "tree";
        this.mode = "040000";
        this.value = "";
        this.key = genKey(file);
        compressWrite();
    }



    /**
     * Deserialize a tree object with treeId and its path.
     * @param Id
     * @param Id
     * @throws IOException
     */
    public static Tree deserialize(String Id) throws Exception {
        try{
            /**
             * Todo: Add your code here.
             */
            File file = new File(path + File.separator + Id);
            if(file.exists()) {
                Tree tree = new Tree();
                tree.treeList = new ArrayList<>();
                tree.fmt = "tree";
                tree.mode = "040000";
                tree.key = Id;

                FileInputStream is = new FileInputStream(file);
                byte[] output = ZLibUtils.decompress(is);//反序列化并解压缩
                is.close();
                tree.value = new String(output);//将字节数组转化为字符串
                return tree;
            }
        }catch (Exception e){
            e.printStackTrace();
        }
        /* Todo: You should delete the return statement before you start. */
        return new Tree();
    }


    /**
     * Sort the files in a certain order. You should consider whether it's a file or a directory.
     * @param fs
     * @return List
     */
    public List sortFile(File[] fs){
        List fileList = Arrays.asList(fs);//将对象型数据的数组转化为List集合
        Collections.sort(fileList, new Comparator<File>() {
            @Override //表示重写方法
            public int compare(File o1, File o2) {
                /* Todo: Add your code here. */
                if(o1.isFile() && o2.isDirectory())
                    return -1;//文件优先，-1表示前者小，1表示前者大
                else if(o1.isDirectory() && o2.isFile())
                    return 1;
                else
                    return o1.getName().compareTo(o2.getName());//同类型的将文件名按字母表排序

            }
        });
        return fileList;
    }

    /**
     * Generate the key of a tree object.
     * @param dir
     * @return String
     * @throws Exception
     */
    public String genKey(File dir) throws Exception{
        /* Todo: Add your code here. */
        File[] fs = dir.listFiles();//listFiles()返回当前目录中的文件和目录；
        for(int i=0; i<fs.length; i++){
            if(fs[i].isDirectory()){ //如果是文件夹
                Tree tree = new Tree(fs[i]);
                treeList.add(tree);
                value += "040000 tree" + tree.getKey() + "\u0020" + fs[i].getName() + "\n";
                tree.compressWrite();
            }
            if(fs[i].isFile()){ //如果是文件
                Blob blob = new Blob(fs[i]);
                treeList.add(blob);
                value += "100644 blob" + blob.getKey() + "\u0020" + fs[i].getName() + "\n";
                blob.compressWrite();
            }
        }
        key = SHA1.getHash(value);
        return key;
    }

    public Tree(LinkedList<String[]> list) throws Exception {
        this.treeList = new ArrayList<>();
        this.fmt = "tree";
        this.mode = "040000";
        String str = "";
        for(int i = 0; i < list.size(); i++){
            str += "100644 blob" + list.get(i)[1] + "\u0020" + list.get(i)[2] + "\n";
            //System.out.println(Blob.deserialize(list.get(i)[1]).getKey());
            treeList.add(Blob.deserialize(list.get(i)[1]));
        }
        //System.out.println(treeList);
        this.value = str;
        this.key = SHA1.getHash(value);

        compressWrite();
    }

    @Override
    public String toString(){
        return "040000 tree " + key;
    }

}